home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / sys / sun3.md / sysPrintf.c.old < prev   
Text File  |  1992-12-18  |  12KB  |  601 lines

  1. /*
  2.  *  sysPrintf --
  3.  *
  4.  *      Perform all formatted printing to the console.
  5.  *
  6.  *    This is adapted from _doprnt.  It has no comments except those put
  7.  *      in _doprnt.  Should be cleaned up and put into Sprite style.  This
  8.  *      copyright is bogus until we rewrite this routine.
  9.  *
  10.  * Copyright (C) 1985 Regents of the University of California
  11.  * All rights reserved.
  12.  */
  13.  
  14. #ifndef lint
  15. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/sys/sun3.md/sysPrintf.c.old,v 9.0 89/09/12 15:20:54 douglis Stable $ SPRITE (Berkeley)";
  16. #endif /* lint */
  17.  
  18. #include "sprite.h"
  19. #include "mach.h"
  20. #include "sys.h"
  21. #include "dbg.h"
  22. #include "dev.h"
  23.  
  24. #define NextArg(argList, type) ((type *)(argList += sizeof(type)))[-1]
  25.  
  26.  
  27. /* Maximum number of digits in any integer (long) representation */
  28. #define    MAXDIGS    11
  29.  
  30. /* Largest (normal length) positive integer */
  31. #define    MAXINT    2147483647
  32.  
  33. /* A long with only the high-order bit turned on */
  34. #define    HIBIT    0x80000000L
  35.  
  36. /* Convert a digit character to the corresponding number */
  37. #define    tonumber(x)    ((x)-'0')
  38.  
  39. /* Convert a number between 0 and 9 to the corresponding digit */
  40. #define    todigit(x)    ((x)+'0')
  41.  
  42. /* Data type for flags */
  43. typedef    char    bool;
  44.  
  45.  
  46. #define max(a,b)    ((a) > (b) ? (a) : (b))
  47. #define min(a,b)    ((a) < (b) ? (a) : (b))
  48.  
  49. /* If this symbol is nonzero, allow '0' as a flag */
  50. #define FZERO 1
  51.  
  52. #define emitchar(c)    { Dev_SyslogPutChar(c); count++; }
  53.  
  54. #ifndef lint
  55.  
  56. /*
  57.  * ----------------------------------------------------------------------------
  58.  *
  59.  * strlen --
  60.  *
  61.  *      Return the length of the string.
  62.  *
  63.  * Results:
  64.  *      The length of the string.
  65.  *
  66.  * Side effects:
  67.  *      None.
  68.  *
  69.  * ----------------------------------------------------------------------------
  70.  */
  71.  
  72. static int
  73. strlen(s)
  74.     register char *s;
  75. {
  76.     register int n;
  77.  
  78.     n = 0;
  79.     while (*s++)
  80.         n++;
  81.     return (n);
  82. }
  83.  
  84.  
  85. /*
  86.  * ----------------------------------------------------------------------------
  87.  *
  88.  * isdigit --
  89.  *
  90.  *      Return true if the character is a digit and false otherwise.
  91.  *
  92.  * Results:
  93.  *      True if the character is a digit and false otherwise.
  94.  *
  95.  * Side effects:
  96.  *      None.
  97.  *
  98.  * ----------------------------------------------------------------------------
  99.  */
  100.  
  101. static int
  102. isdigit(c)
  103.     char c;
  104. {
  105.     return(c >= '0' && c <= '9');
  106. }
  107.  
  108.  
  109.  
  110. /*
  111.  * ----------------------------------------------------------------------------
  112.  *
  113.  * Sys_DoPrintf --
  114.  *
  115.  *      Perform a C style printf to the monitor.  This has all of the
  116.  *      functionality of a normal C printf except for floating point.
  117.  *
  118.  * Results:
  119.  *      Number of characters printed.
  120.  *
  121.  * Side effects:
  122.  *      None.
  123.  *
  124.  * ----------------------------------------------------------------------------
  125.  */
  126.  
  127. int
  128. Sys_DoPrintf(format, argList)
  129.     char *format;
  130.     char *argList;
  131. {
  132.     /* Current position in format */
  133.     char *cp;
  134.  
  135.     /* Starting and ending points for value to be printed */
  136.     char *bp, *p;
  137.  
  138.     /* Field width and precision */
  139.     int width, prec;
  140.  
  141.     /* Format code */
  142.     char fcode;
  143.  
  144.     /* Number of padding zeroes required on the left */
  145.     int lzero;
  146.  
  147.     /* Flags - nonzero if corresponding character appears in format */
  148.     bool length;        /* l */
  149.     bool fplus;        /* + */
  150.     bool fminus;        /* - */
  151.     bool fblank;        /* blank */
  152.     bool fsharp;        /* # */
  153.     bool fzero;        /* 0 */
  154.  
  155.     /* Pointer to sign, "0x", "0X", or empty */
  156.     char *prefix;
  157.  
  158.     char buf[MAXDIGS];
  159.  
  160.     /* The value being converted, if integer */
  161.     long val;
  162.  
  163.     /* Set to point to a translate table for digits of whatever radix */
  164.     char *tab;
  165.  
  166.     /* Work variables */
  167.     int n, hradix, lowbit;
  168.  
  169.     /* count of output characters */
  170.     int count;
  171.  
  172.     cp = format;
  173.     count = 0;
  174.  
  175.     /*
  176.      *    The main loop -- this loop goes through one iteration
  177.      *    for each ordinary character or format specification.
  178.      */
  179.     while (*cp)
  180.         if (*cp != '%') {
  181.             /* Ordinary (non-%) character */
  182.             emitchar(*cp);
  183.             cp++;
  184.         } else {
  185.             /*
  186.              *    % has been found.
  187.              *    First, parse the format specification.
  188.              */
  189.  
  190.             /* Scan the <flags> */
  191.             fplus = fminus = fblank = fsharp = 0;
  192. #if FZERO
  193.             fzero = 0;
  194. #endif
  195.         scan:    switch (*++cp) {
  196.             case '+':
  197.                 fplus = 1;
  198.                 goto scan;
  199.             case '-':
  200.                 fminus = 1;
  201.                 goto scan;
  202.             case ' ':
  203.                 fblank = 1;
  204.                 goto scan;
  205.             case '#':
  206.                 fsharp = 1;
  207.                 goto scan;
  208. #if FZERO
  209.             case '0':
  210.                 fzero = 1;
  211.                 goto scan;
  212. #endif
  213.             }
  214.  
  215.             /* Scan the field width */
  216.             if (*cp == '*') {
  217.                 width = NextArg(argList, int);
  218.                 if (width < 0) {
  219.                     width = -width;
  220.                     fminus = 1;
  221.                 }
  222.                 cp++;
  223.             } else {
  224.                 width = 0;
  225.                 while (isdigit(*cp)) {
  226.                     n = tonumber(*cp++);
  227.                     width = width * 10 + n;
  228.                 }
  229.             }
  230.  
  231.             /* Scan the precision */
  232.             if (*cp == '.') {
  233.  
  234.                 /* '*' instead of digits? */
  235.                 if (*++cp == '*') {
  236.                     prec = NextArg(argList, int);
  237.                     cp++;
  238.                 } else {
  239.                     prec = 0;
  240.                     while (isdigit(*cp)) {
  241.                         n = tonumber(*cp++);
  242.                         prec = prec * 10 + n;
  243.                     }
  244.                 }
  245.             } else
  246.                 prec = -1;
  247.  
  248.             /* Scan the length modifier */
  249.             length = 0;
  250.             switch (*cp) {
  251.             case 'l':
  252.                 length = 1;
  253.                 /* No break */
  254.             case 'h':
  255.                 cp++;
  256.             }
  257.  
  258.             /*
  259.              *    The character addressed by cp must be the
  260.              *    format letter -- there is nothing left for
  261.              *    it to be.
  262.              *
  263.              *    The status of the +, -, #, blank, and 0
  264.              *    flags are reflected in the variables
  265.              *    "fplus", "fminus", "fsharp", "fblank",
  266.              *    and "fzero", respectively.
  267.              *    "width" and "prec" contain numbers
  268.              *    corresponding to the digit strings
  269.              *    before and after the decimal point,
  270.              *    respectively. If there was no decimal
  271.              *    point, "prec" is -1.
  272.              *
  273.              *    The following switch sets things up
  274.              *    for printing.  What ultimately gets
  275.              *    printed will be padding blanks, a prefix,
  276.              *    left padding zeroes, a value, right padding
  277.              *    zeroes, a suffix, and more padding
  278.              *    blanks.  Padding blanks will not appear
  279.              *    simultaneously on both the left and the
  280.              *    right.  Each case in this switch will
  281.              *    compute the value, and leave in several
  282.              *    variables the information necessary to
  283.              *    construct what is to be printed.
  284.              *
  285.              *    The prefix is a sign, a blank, "0x", "0X",
  286.              *    or null, and is addressed by "prefix".
  287.              *
  288.              *    The suffix is either null or an exponent,
  289.              *    and is addressed by "suffix".
  290.              *
  291.              *    The value to be printed starts at "bp"
  292.              *    and continues up to and not including "p".
  293.              *
  294.              *    "lzero" and "rzero" will contain the number
  295.              *    of padding zeroes required on the left
  296.              *    and right, respectively.  If either of
  297.              *    these variables is negative, it will be
  298.              *    treated as if it were zero.
  299.              *
  300.              *    The number of padding blanks, and whether
  301.              *    they go on the left or the right, will be
  302.              *    computed on exit from the switch.
  303.              */
  304.             
  305.             lzero = 0;
  306.             prefix = "";
  307.             switch (fcode = *cp++) {
  308.             /*
  309.              *    fixed point representations
  310.              *
  311.              *    "hradix" is half the radix for the conversion.
  312.              *    Conversion is unsigned unless fcode is 'd'.
  313.              *    HIBIT is 1000...000 binary, and is equal to
  314.              *        the maximum negative number.
  315.              *    We assume a 2's complement machine
  316.              */
  317.  
  318.             case 'D':
  319.             case 'U':
  320.                 length = 1;
  321.             case 'd':
  322.             case 'u':
  323.                 hradix = 5;
  324.                 goto fixed;
  325.  
  326.             case 'O':
  327.                 length = 1;
  328.             case 'o':
  329.                 hradix = 4;
  330.                 goto fixed;
  331.  
  332.             case 'X':
  333.             case 'x':
  334.                 hradix = 8;
  335.  
  336.             fixed:
  337.                 /* Establish default precision */
  338.                 if (prec < 0)
  339.                     prec = 1;
  340.  
  341.                 /* Fetch the argument to be printed */
  342.                 if (length)
  343.                     val = NextArg(argList, long);
  344.                 else if (fcode == 'd')
  345.                     val = NextArg(argList, int);
  346.                 else
  347.                     val = NextArg(argList, unsigned);
  348.  
  349.                 /* If signed conversion, establish sign */
  350.                 if (fcode == 'd' || fcode == 'D') {
  351.                     if (val < 0) {
  352.                         prefix = "-";
  353.                         /*
  354.                          *    Negate, checking in
  355.                          *    advance for possible
  356.                          *    overflow.
  357.                          */
  358.                         if (val != HIBIT)
  359.                             val = -val;
  360.                     } else if (fplus)
  361.                         prefix = "+";
  362.                     else if (fblank)
  363.                         prefix = " ";
  364.                 }
  365. #if FZERO
  366.                 if (fzero) {
  367.                     int n = width - strlen(prefix);
  368.                     if (n > prec)
  369.                         prec = n;
  370.                 }
  371. #endif
  372.                 /* Set translate table for digits */
  373.                 if (fcode == 'X')
  374.                     tab = "0123456789ABCDEF";
  375.                 else
  376.                     tab = "0123456789abcdef";
  377.  
  378.                 /* Develop the digits of the value */
  379.                 p = bp = buf + MAXDIGS;
  380.                 while (val) {
  381.                     lowbit = val & 1;
  382.                     val = (val >> 1) & ~HIBIT;
  383.                     *--bp = tab[val % hradix * 2 + lowbit];
  384.                     val /= hradix;
  385.                 }
  386.  
  387.                 /* Calculate padding zero requirement */
  388.                 lzero = bp - p + prec;
  389.  
  390.                 /* Handle the # flag */
  391.                 if (fsharp && bp != p)
  392.                     switch (fcode) {
  393.                     case 'o':
  394.                         if (lzero < 1)
  395.                             lzero = 1;
  396.                         break;
  397.                     case 'x':
  398.                         prefix = "0x";
  399.                         break;
  400.                     case 'X':
  401.                         prefix = "0X";
  402.                         break;
  403.                     }
  404.  
  405.                 break;
  406.             case 'c':
  407.                 buf[0] = NextArg(argList, int);
  408.                 bp = &buf[0];
  409.                 p = bp + 1;
  410.                 break;
  411.  
  412.             case 's':
  413.                 bp = NextArg(argList, char *);
  414.                 if (prec < 0)
  415.                     prec = MAXINT;
  416.                 /* avoid *(0) */
  417.                 if (bp == NULL)
  418.                     bp = "(null)";
  419.                 for (n=0; *bp++ != '\0' && n < prec; n++)
  420.                     ;
  421.                 p = --bp;
  422.                 bp -= n;
  423.                 break;
  424.  
  425.             case '\0':
  426.                 cp--;
  427.                 break;
  428.  
  429.         /*    case '%':    */
  430.             default:
  431.                 p = bp = &fcode;
  432.                 p++;
  433.                 break;
  434.  
  435.             }
  436.             if (fcode != '\0') {
  437.                 /* Calculate number of padding blanks */
  438.                 int nblank;
  439.                 nblank = width
  440.                     - (p - bp)
  441.                     - (lzero < 0? 0: lzero)
  442.                     - strlen(prefix);
  443.  
  444.                 /* Blanks on left if required */
  445.                 if (!fminus)
  446.                     while (--nblank >= 0)
  447.                         emitchar(' ');
  448.  
  449.                 /* Prefix, if any */
  450.                 while (*prefix != '\0') {
  451.                     emitchar(*prefix);
  452.                     prefix++;
  453.                 }
  454.  
  455.                 /* Zeroes on the left */
  456.                 while (--lzero >= 0)
  457.                     emitchar('0');
  458.                 
  459.                 /* The value itself */
  460.                 while (bp < p) {
  461.                     emitchar(*bp);
  462.                     bp++;
  463.                 }
  464.                 /* Blanks on the right if required */
  465.                 if (fminus)
  466.                     while (--nblank >= 0)
  467.                         emitchar(' ');
  468.             }
  469.         }
  470.  
  471.     return (count);
  472. }
  473. #else /* lint */
  474. /*
  475.  * Header just for linting.
  476.  */
  477. /*ARGSUSED*/
  478. int
  479. Sys_DoPrintf(format, argList)
  480.     char *format;
  481.     char *argList;
  482. {
  483.     return 0;
  484. }
  485. #endif /* lint */
  486.  
  487. Boolean    sysPanicing = FALSE;
  488.  
  489.  
  490. /*
  491.  * ----------------------------------------------------------------------------
  492.  *
  493.  * Sys_Panic --
  494.  *
  495.  *      Print a formatted string to the monitor and then either abort to the
  496.  *      debugger or continue depending on the panic level.
  497.  *
  498.  * Results:
  499.  *      None.
  500.  *
  501.  * Side effects:
  502.  *      None.
  503.  *
  504.  * ----------------------------------------------------------------------------
  505.  */
  506.  
  507. /*VARARGS2*/
  508. void
  509. Sys_Panic(level, format, args)
  510.     Sys_PanicLevel     level;
  511.     char         *format;
  512.     int         args;
  513. {
  514.     if (level == SYS_WARNING) {
  515.         Sys_UnSafePrintf("Warning: ");
  516.     } else {
  517.     Dev_SyslogDebug(TRUE);
  518.         Sys_UnSafePrintf("Fatal Error: ");
  519.     }
  520.  
  521.     (void) Sys_DoPrintf(format, (char *) &args);
  522.  
  523.     if (level == SYS_FATAL) {
  524.     /*
  525.      * Make sure the monitor is enabled.
  526.      */
  527.     Dev_VidEnable(TRUE);
  528.  
  529.     sysPanicing = TRUE;
  530.         DBG_CALL;
  531.     Dev_SyslogDebug(FALSE);
  532.     }
  533. }
  534.  
  535.  
  536. /*
  537.  * ----------------------------------------------------------------------------
  538.  *
  539.  * Sys_Printf --
  540.  *
  541.  *      Perform a C style printf except for floating point.
  542.  *    Enterrupts are disabled during the printf to the console.
  543.  *    Sys_UnSafePrintf should be used instead if that's undesirable.
  544.  *
  545.  * Results:
  546.  *      None.
  547.  *
  548.  * Side effects:
  549.  *      None.
  550.  *
  551.  * ----------------------------------------------------------------------------
  552.  */
  553.  
  554. /*VARARGS1*/
  555. void
  556. Sys_UnSafePrintf(format, args)
  557.     char *format;
  558.     int args;
  559. {
  560.     (void) Sys_DoPrintf(format, (char *) &args);
  561. }
  562. /*VARARGS1*/
  563. void
  564. Sys_Printf(format, args)
  565.     char *format;
  566.     int args;
  567. {
  568.     DISABLE_INTR();
  569.     (void) Sys_DoPrintf(format, (char *) &args);
  570.     ENABLE_INTR();
  571. }
  572.  
  573.  
  574. /*
  575.  * ----------------------------------------------------------------------------
  576.  *
  577.  * Sys_SafePrintf --
  578.  *
  579.  *      Perform a C style printf except for floating point.
  580.  *    Interrupts are disabled while printing.
  581.  *
  582.  * Results:
  583.  *      None.
  584.  *
  585.  * Side effects:
  586.  *      None.
  587.  *
  588.  * ----------------------------------------------------------------------------
  589.  */
  590.  
  591. /*VARARGS1*/
  592. void
  593. Sys_SafePrintf(format, args)
  594.     char *format;
  595.     int args;
  596. {
  597.     DISABLE_INTR();
  598.     (void) Sys_DoPrintf(format, (char *) &args);
  599.     ENABLE_INTR();
  600. }
  601.